package com.sinodata.bsm.cicp.collector.sybase;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.AbstractJDBCCollector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.DBConnectionUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * Monitor.java
 * <p>
 * 
 * @author 管普贵 guanpg@uni-mon.com
 * @version 2.0
 * @Date Jan 8, 2010
 */
public class Monitor extends AbstractJDBCCollector {
    private static final Logger logger = Logger.getLogger(Monitor.class);
    private static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static Pattern p1 = Pattern.compile("\\d+\\((\\d+)\\)$");
    private static Pattern p2 = Pattern.compile("\\d+\\(\\d+\\)-(\\d+)%$");

    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        try {
            String[] propMetas = getPropMeta();
            //        String serverName = this.getParamMap().get("服务器名");
            String serverName = this.getParamMap().get("ServerName");
            System.out.println(serverName);
            String sql = "master.dbo.sp_monitor";
            String[] rs = this.getStrings(serverName, sql, ip);

            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
            for (int i = 0; i < propMetas.length; i++) {
                propValues[i] = ResPropertyValue.createPropValue(rs[i], propMetas[i]);
            }
            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (Exception ex) {
            logger.error("failed to collect sybase monitor", ex);
            throw new CollectorException(ex);
        }
        return values;
    }

    private String[] getStrings(String serverName, String sql, String ip) throws CollectorException {
        String[] propValArr = new String[13];
        CallableStatement cstm = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
            conn = DBConnectionUtil.getInstance().getConnection("sybase", ip, serverName);
            if (conn != null) {// 判断是否建立连接
                cstm = conn.prepareCall(sql);
                cstm.setQueryTimeout(10);
                rs = cstm.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();
                if (rs != null)
                    propValArr = setValue(propValArr, rsmd, rs);
                while (cstm.getMoreResults()) {
                    rs = cstm.getResultSet();
                    rsmd = rs.getMetaData();
                    if (rs != null)
                        propValArr = setValue(propValArr, rsmd, rs);
                    rs = null;
                }
                propValArr = match(propValArr);
            }
        } catch (SQLException sqle) {
            logger.error("when query sybase database ", sqle);
            throw new CollectorException(sqle);
        } catch (IOException ioex) {
            logger.error("when query sybase database ", ioex);
            throw new CollectorException(ioex);
        } catch (Exception ex) {
            logger.error("when query sybase database ", ex);
            throw new CollectorException(ex);
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (cstm != null)
                    cstm.close();
            } catch (SQLException e) {
                logger.error("close database failed", e);
                throw new CollectorException(e);
            }

            DBConnectionUtil.getInstance().returnConnection(conn);
        }
        return propValArr;
    }

    public String[] getParamMeta() {
        return new String[] { "ServerName" };
    }

    public String[] getPropMeta() {
        //        return new String[] { "性能采集最后运行时间", "当前时间", "当前时间与最后运行时间差", "执行AS工作的CPU时间", "执行I/O操作的CPU时间", "处于空闲状态的CPU时间", "读取的输入包的数目", "写入的输出包的数目", "读写包时检测到的错误数", "磁盘读取操作的数目", "磁盘写入操作的数目", "读写数据时检测到的错误数", "内存大小" };
        return new String[] { "PerformanceCollectLastRunTime", "CurrentTime", "TimeDifferenceBetweenCurrentAndLastRunTime", "ASCPUTime", "IOCPUTime", "CPUFreeTime", "ReadInputPacketNum", "WriteOutputPacketNum", "DetectWRPacketNum", "DiskReadNum", "DiskWriteNum", "ReadDetectedErrorsNum", "MemorySize" };
    }

    public String[] match(String[] str) {
        for (int i = 0; i < str.length; i++) {
            str[i] = getString(str[i]);
            Matcher m1 = p1.matcher(str[i].trim());
            if (m1.matches()) {
                str[i] = m1.group(1);
            }
            Matcher m2 = p2.matcher(str[i].trim());
            if (m2.matches()) {
                str[i] = m2.group(1);
            }
        }
        return str;
    }

    public String[] setValue(String[] str, ResultSetMetaData rsmd, ResultSet rs) throws SQLException {
        if (!rs.next())
            return str;
        rsmd = rs.getMetaData();
        int count = rsmd.getColumnCount();
        for (int i = 1; i <= count; i++) {
            String field = rsmd.getColumnName(i).trim();
            // logger.info(field+":"+rsmd.getColumnTypeName(i));
            if (field.equals("lastrun")) {
                str[0] = sdf.format(rs.getTimestamp("last_run"));
            } else if (field.equals("current_run")) {
                str[1] = sdf.format(rs.getTimestamp("current_run"));
            } else if (field.equals("seconds")) {
                str[2] = rs.getString("seconds");
            } else if (field.equals("cpu_busy")) {
                str[3] = rs.getString("cpu_busy");
            } else if (field.equals("io_busy")) {
                str[4] = rs.getString("io_busy");
            } else if (field.equals("idle")) {
                str[5] = rs.getString("idle");
            } else if (field.equals("packets_received")) {
                str[6] = rs.getString("packets_received");
            } else if (field.equals("packets_sent")) {
                str[7] = rs.getString("packets_sent");
            } else if (field.equals("packet_errors")) {
                str[8] = rs.getString("packet_errors");
            } else if (field.equals("total_read")) {
                str[9] = rs.getString("total_read");
            } else if (field.equals("total_write")) {
                str[10] = rs.getString("total_write");
            } else if (field.equals("total_errors")) {
                str[11] = rs.getString("total_errors");
            } else if (field.equals("connections")) {
                str[12] = rs.getString("connections");
            }
        }
        return str;
    }

    private static String getString(String str) {
        return str == null ? "" : str.trim();
    }
}
